using BuildingBlocks.Abstractions.Permissions;
using Identity.Domain.Aggregates;
using Identity.Infrastructure.Persistence.Entities;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace Identity.Infrastructure.HostedServices
{
    public class IdentityStartupTasks : IHostedService
    {
        private readonly IServiceProvider _serviceProvider;
        

        public IdentityStartupTasks(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
            
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            using var scope = _serviceProvider.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

            var scanner = scope.ServiceProvider.GetRequiredService<IPermissionProvider>();
            var permissions = scanner.GetPermissions().ToList();

            var existingBindings = context.ApiPermissionBindings
               .Where(a => a.FromServiceName == "IdentityService")
               .ToList();

            var existingResourceIds = existingBindings.Select(b => b.ResourceId).ToHashSet();
            var incomingResourceIds = permissions.Select(p => p.resourceId).ToHashSet();

            var toDelete = existingBindings.Where(b => !incomingResourceIds.Contains(b.ResourceId)).ToList();
            context.ApiPermissionBindings.RemoveRange(toDelete);
            
            var toAdd = permissions
                .Where(p => !existingResourceIds.Contains(p.resourceId))
                .Select(p => ApiPermissionBinding.Create(
                        p.resourceId,
                        p.description,
                       "IdentityService",
                        Domain.ValueObjects.PermissionScope.Local))
                        .ToList();

            context.ApiPermissionBindings.AddRange(toAdd);

           await  context.SaveChangesAsync(cancellationToken);
        }

        public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
}